﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ExportPhysics.DTO
{
    public class vector2df
    {
        public vector2df()
        {
            X = 0;
            Y = 0;
        }

        public vector2df(float nx, float ny)
        {
            X = nx;
            Y = ny;
        }
        public static vector2df operator -(vector2df c)
        {
            tmp.X = -c.X;
            tmp.Y = -c.Y;
            return tmp;
        }



        public static vector2df operator -(vector2df c1, vector2df c2)
        {
            tmp.X = c1.X - c2.X;
            tmp.Y = c1.Y - c2.Y;
            return tmp;
        }
        public static vector2df operator -(vector2df c1, float v)
        {
            tmp.X = c1.X - v;
            tmp.Y = c1.Y - v;
            return tmp;
        }

        public static vector2df operator +(vector2df c1, vector2df c2)
        {
            tmp.X = c1.X + c2.X;
            tmp.Y = c1.Y + c2.Y;
            return tmp;
        }
        public static vector2df operator +(vector2df c1, float v)
        {
            tmp.X = c1.X + v;
            tmp.Y = c1.Y + v;
            return tmp;
        }

        public static vector2df operator *(vector2df c1, vector2df c2)
        {
            tmp.X = c1.X * c2.X;
            tmp.Y = c1.Y * c2.Y;
            return tmp;
        }
        public static vector2df operator *(vector2df c1, float v)
        {
            tmp.X = c1.X * v;
            tmp.Y = c1.Y * v;
            return tmp;
        }

        public static vector2df operator /(vector2df c1, vector2df c2)
        {
            tmp.X = c1.X / c2.X;
            tmp.Y = c1.Y / c2.Y;
            return tmp;
        }
        public static vector2df operator /(vector2df c1, float v)
        {
            tmp.X = c1.X * v;
            tmp.Y = c1.Y * v;
            return tmp;
        }

        public static bool operator <=(vector2df c1, vector2df c2)
        {
            return c1.X <= c2.X && c1.Y <= c2.Y;
        }
        public static bool operator >=(vector2df c1, vector2df c2)
        {
            return c1.X >= c2.X && c1.Y >= c2.Y;
        }

        public static bool operator <(vector2df c1, vector2df c2)
        {
            return c1.X < c2.X && c1.Y < c2.Y;
        }
        public static bool operator >(vector2df c1, vector2df c2)
        {
            return c1.X > c2.X && c1.Y > c2.Y;
        }

        //public static bool operator ==(vector2df c1, vector2df c2)
        //{
        //    return c1.X == c2.X && c1.Y == c2.Y;
        //}
        //public static bool operator !=(vector2df c1, vector2df c2)
        //{
        //    return c1.X != c2.X || c1.Y != c2.Y;
        //}

        public bool equals(vector2df other)
        {
            return X == other.X && Y == other.Y;
        }

        public vector2df set(float nx, float ny)
        {
            X = nx;
            Y = ny;
            return this;
        }
        public vector2df set(vector2df other)
        {
            X = other.X;
            Y = other.Y;
            return this;
        }
        public float getLength() { return (float)Math.Sqrt((X * X + Y * Y)); }

        public float getLengthSQ() { return X * X + Y * Y; }

        public float dotProduct(vector2df other)
        {
            return X * other.X + Y * other.Y;
        }

        public float getDistanceFrom(vector2df other)
        {
            tmp.X = X - other.X;
            tmp.Y = Y - other.Y;
            return tmp.getLength();
        }

        private static vector2df tmp = new vector2df();
        public float getDistanceFromSQ(vector2df other)
        {
            tmp.X = X - other.X;
            tmp.Y = Y - other.Y;
            return tmp.getLengthSQ();
        }

       

        public vector2df normalize()
        {
            float l = X * X + Y * Y;
            if (l == 0)
                return this;
            l = 1/(float)(Math.Sqrt(l));
            X *= l;
            Y *= l;
            return this;
        }

      
        public bool isBetweenPoints(vector2df begin, vector2df end)
        {
            if (begin.X != end.X)
            {
                return ((begin.X <= X && X <= end.X) ||
                    (begin.X >= X && X >= end.X));
            }
            else
            {
                return ((begin.Y <= Y && Y <= end.Y) ||
                    (begin.Y >= Y && Y >= end.Y));
            }
        }

        public vector2df getInterpolated(vector2df other, float d)
        {
            float inv = (float)1.0 - d;
            return new vector2df(other.X * inv + X * d, other.Y * inv + Y * d);
        }

        public vector2df getInterpolated_quadratic(vector2df v2, vector2df v3, float d)
        {
            // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d;
            float inv = (float)1.0 - d;
            float mul0 = inv * inv;
            float mul1 = (float)2.0 * d * inv;
            float mul2 = d * d;

            return new vector2df(X * mul0 + v2.X * mul1 + v3.X * mul2,
                        Y * mul0 + v2.Y * mul1 + v3.Y * mul2);
        }

        public vector2df interpolate(vector2df a, vector2df b, float t)
        {
            X = b.X + ((a.X - b.X) * t);
            Y = b.Y + ((a.Y - b.Y) * t);
            return this;
        }
        //! X coordinate of vector.
        public float X;
        //! Y coordinate of vector.
        public float Y;
    }
    public class vector2di
    {
        public vector2di()
        {
            X = 0;
            Y = 0;
        }

        public vector2di(int nx, int ny)
        {
            X = nx;
            Y = ny;
        }
        public static vector2di operator -(vector2di c)
        {
            tmp.X = c.X;
            tmp.Y = c.Y;
            return tmp;
        }



        public static vector2di operator -(vector2di c1, vector2di c2)
        {
            tmp.X = c1.X - c2.X;
            tmp.Y = c1.Y - c2.Y;
            return tmp;
        }
        public static vector2di operator -(vector2di c1, int v)
        {
            tmp.X = c1.X - v;
            tmp.Y = c1.Y - v;
            return tmp;
        }

        public static vector2di operator +(vector2di c1, vector2di c2)
        {
            tmp.X = c1.X + c2.X;
            tmp.Y = c1.Y + c2.Y;
            return tmp;
        }
        public static vector2di operator +(vector2di c1, int v)
        {
            tmp.X = c1.X + v;
            tmp.Y = c1.Y + v;
            return tmp;
        }

        public static vector2di operator *(vector2di c1, vector2di c2)
        {
            tmp.X = c1.X * c2.X;
            tmp.Y = c1.Y * c2.Y;
            return tmp;
        }
        public static vector2di operator *(vector2di c1, int v)
        {
            tmp.X = c1.X * v;
            tmp.Y = c1.Y * v;
            return tmp;
        }

        public static vector2di operator /(vector2di c1, vector2di c2)
        {
            tmp.X = c1.X / c2.X;
            tmp.Y = c1.Y / c2.Y;
            return tmp;
        }

        public static vector2di operator /(vector2di c1, int v)
        {            
            tmp.X = c1.X * v;
            tmp.Y = c1.Y * v;
            return tmp;
        }

        public static bool operator <=(vector2di c1, vector2di c2)
        {
            return c1.X <= c2.X && c1.Y <= c2.Y;
        }
        public static bool operator >=(vector2di c1, vector2di c2)
        {
            return c1.X >= c2.X && c1.Y >= c2.Y;
        }

        public static bool operator <(vector2di c1, vector2di c2)
        {
            return c1.X < c2.X && c1.Y < c2.Y;
        }
        public static bool operator >(vector2di c1, vector2di c2)
        {
            return c1.X > c2.X && c1.Y > c2.Y;
        }

        public static bool operator ==(vector2di c1, vector2di c2)
        {
            return c1.X == c2.X && c1.Y == c2.Y;
        }
        public static bool operator !=(vector2di c1, vector2di c2)
        {
            return c1.X != c2.X || c1.Y != c2.Y;
        }

        public bool equals(vector2di other)
        {
            return X == other.X && Y == other.Y;
        }

        public vector2di set(int nx, int ny)
        {
            X = nx;
            Y = ny;
            return this;
        }
        public vector2di set(vector2di other)
        {
            X = other.X;
            Y = other.Y;
            return this;
        }
        public int getLength() { return (int)Math.Sqrt((X * X + Y * Y)); }

        public int getLengthSQ() { return X * X + Y * Y; }

        public int dotProduct(vector2di other)
        {
            return X * other.X + Y * other.Y;
        }

        public int getDistanceFrom(vector2di other)
        {
            tmp.X = X - other.X;
            tmp.Y = Y - other.Y;
            return tmp.getLength();
        }

        private static vector2di tmp = new vector2di();
        public int getDistanceFromSQ(vector2di other)
        {
            tmp.X = X - other.X;
            tmp.Y = Y - other.Y;
            return tmp.getLengthSQ();
        }

        public vector2di normalize()
        {
            int l = X * X + Y * Y;
            if (l == 0)
                return this;
            l = (int)(1/(float)Math.Sqrt(l));
            X *= l;
            Y *= l;
            return this;
        }

       
        public bool isBetweenPoints(vector2di begin, vector2di end)
        {
            if (begin.X != end.X)
            {
                return ((begin.X <= X && X <= end.X) ||
                    (begin.X >= X && X >= end.X));
            }
            else
            {
                return ((begin.Y <= Y && Y <= end.Y) ||
                    (begin.Y >= Y && Y >= end.Y));
            }
        }

        public vector2di getInterpolated(vector2di other, float d)
        {
            int inv = (int)(1.0 - d);
            return new vector2di((int)(other.X * inv + X * d), (int)(other.Y * inv + Y * d));
        }

        public vector2di getInterpolated_quadratic(vector2di v2, vector2di v3, int d)
        {
            // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d;
            int inv = (int)1.0 - d;
            int mul0 = inv * inv;
            int mul1 = (int)2.0 * d * inv;
            int mul2 = d * d;

            return new vector2di(X * mul0 + v2.X * mul1 + v3.X * mul2,
                        Y * mul0 + v2.Y * mul1 + v3.Y * mul2);
        }

        public vector2di interpolate(vector2di a, vector2di b, float t)
        {
            X = (int)(b.X + ((a.X - b.X) * t));
            Y = (int)(b.Y + ((a.Y - b.Y) * t));
            return this;
        }
        //! X coordinate of vector.
        public int X;
        //! Y coordinate of vector.
        public int Y;
    }



}
